home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 June: System Software / Dev.CD Jun 97 SSW.toast / What's New? / Sample Code / Toolbox / FinderDragPro / GetIconSuiteFromFinder.c < prev    next >
Encoding:
Text File  |  1997-04-23  |  12.2 KB  |  492 lines  |  [TEXT/CWIE]

  1.     //
  2.     //    LEGAL NOTICE
  3.     //    ============
  4.     //
  5.     //     You may incorporate this sample code into your applications
  6.     //     without restriction. This sample code has been provided "AS
  7.     //     IS" and the responsibility for its operation is 100% yours.
  8.     //     You are not permitted to redistribute the source as "Apple
  9.     //     sample code" after having made changes. If you're going to
  10.     //     re-distribute the source, we require that you make it clear
  11.     //     in the source that the code was descended from Apple sample
  12.     //     code, but that you've made changes.
  13.     //
  14.     //    REVISION HISTORY
  15.     //    ================
  16.     //
  17.     //    06/09/95    NG    last touched
  18.     //    08/23/96    PG    stolen from Nitin's old FinderDrag project
  19.     //    04/21/97    PG    pascal programs can be written in any language
  20.     //
  21.     
  22.  
  23. #ifndef __ICONS__
  24. #    include <Icons.h>
  25. #endif
  26.  
  27. #ifndef __ALIASES__
  28. #    include <Aliases.h>
  29. #endif
  30.  
  31. #ifndef __AEREGISTRY__
  32. #    include <AERegistry.h>
  33. #endif
  34.  
  35. #ifndef __GESTALT__
  36. #    include <Gestalt.h>
  37. #endif
  38.  
  39. #ifndef __AEPACKOBJECT__
  40. #    include <AEPackObject.h>
  41. #endif
  42.  
  43. #ifndef __AEOBJECTS__
  44. #    include <AEObjects.h>
  45. #endif
  46.  
  47. #ifndef __ERRORS__
  48. #    include <Errors.h>
  49. #endif
  50.  
  51. #ifndef __TEXTUTILS__
  52. #    include <TextUtils.h>
  53. #endif
  54.  
  55. #include "GetIconSuiteFromFinder.h"
  56.  
  57. #define require(x,y) do { if (!(x)) goto y; } while (0)
  58.  
  59. AEDesc pFinderTarget;
  60.  
  61. //----------------------------------------------------------------------------
  62. // FinderIsRunning
  63. //
  64. // Walk the Process Mgr list to check if the Finder is running
  65. //----------------------------------------------------------------------------
  66.  
  67. static Boolean FinderIsRunning (void)
  68. {
  69.     OSErr            err;
  70.     ProcessInfoRec    pInfo;
  71.     ProcessSerialNumber    psn;
  72.     Boolean            foundIt;
  73.  
  74.     foundIt = false;
  75.     psn.highLongOfPSN = 0; psn.lowLongOfPSN = kNoProcess;
  76.  
  77.     while ((foundIt == false) && (GetNextProcess(&psn) == noErr)) {
  78.         pInfo.processName         = NULL;
  79.         pInfo.processAppSpec     = NULL;
  80.         pInfo.processInfoLength    = sizeof(ProcessInfoRec);
  81.     
  82.         err = GetProcessInformation(&psn, &pInfo);
  83.     
  84.         if ((err == noErr) 
  85.             && (pInfo.processSignature == 'MACS') 
  86.             && (pInfo.processType == 'FNDR'))
  87.             
  88.             foundIt = true;
  89.     }
  90.     
  91.     return foundIt;
  92. }
  93.  
  94. //----------------------------------------------------------------------------
  95. // HaveScriptableFinder
  96. //
  97. // We have it if the Gestalt bit is set and the Finder is running
  98. //----------------------------------------------------------------------------
  99.  
  100. static Boolean HaveScriptableFinder(void)
  101. {
  102.     long         response;
  103.     Boolean        haveScriptableFinder;
  104.     OSErr        err;
  105.  
  106.     haveScriptableFinder = false;
  107.     
  108.     err = Gestalt(gestaltFinderAttr, &response);
  109.     require(err == noErr, Gestalt);
  110.  
  111.     if ((response & (1 << gestaltOSLCompliantFinder)) && (FinderIsRunning()))
  112.         haveScriptableFinder = true;
  113.  
  114. Gestalt:
  115.     return haveScriptableFinder;
  116. }
  117.  
  118. //----------------------------------------------------------------------------
  119. // SendAppleEvent
  120. //----------------------------------------------------------------------------
  121.  
  122. static OSErr SendAppleEvent(AppleEvent *ae, AppleEvent *reply, AESendMode sendMode)
  123. {
  124.     AppleEvent    throwAwayReply;
  125.     OSErr        err;
  126.  
  127.     if (reply == NULL) {
  128.         err = AESend(ae, &throwAwayReply, sendMode, 
  129.                     kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  130.         if (err == noErr)
  131.             AEDisposeDesc(&throwAwayReply);
  132.     }
  133.     else
  134.         err = AESend(ae, reply, sendMode, 
  135.                     kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  136.  
  137.     return err;
  138. }
  139.  
  140.  
  141. //----------------------------------------------------------------------------
  142. // MakeAppleEvent
  143. //----------------------------------------------------------------------------
  144.  
  145. static pascal OSErr MakeAppleEvent
  146.     (AEEventClass aeClass, AEEventID aeID, AEDesc *target, AppleEvent *ae)
  147. {
  148.     OSErr err = noErr;
  149.  
  150.     if (target->dataHandle == nil)
  151.     {
  152.         DescType finderSig = 'MACS';
  153.  
  154.         err = AECreateDesc(typeApplSignature, (Ptr) &finderSig,
  155.             sizeof(DescType), target);
  156.     }
  157.  
  158.     if (!err)
  159.         err = AECreateAppleEvent(aeClass, aeID, target, 
  160.             kAutoGenerateReturnID, kAnyTransactionID, ae);
  161.     
  162.     return err;
  163. }
  164.  
  165. //----------------------------------------------------------------------------
  166. // MakeSpecifierForSelection
  167. //----------------------------------------------------------------------------
  168.  
  169. static OSErr MakeSpecifierForSelection(AEDesc *selectionSpecifier)
  170. {
  171.     OSErr         err;
  172.     DescType     descData;
  173.     AEDesc        keyData, nullDescriptor;
  174.     
  175.     nullDescriptor.descriptorType = typeNull;
  176.     nullDescriptor.dataHandle = NULL;
  177.  
  178.     //
  179.     // Make a descriptor whose type is 'typeType' and whose
  180.     // contents are 'pSelection' (defined in FinderRegistry.h).
  181.     // This descriptor specifies the property of the null container
  182.     // that we are interested in--in this case, the selection.
  183.     //
  184.     descData = pSelection;
  185.     err = AECreateDesc(typeType, (Ptr) &descData, sizeof(DescType), &keyData);
  186.     require(err == noErr, AECreateDesc);
  187.     
  188.     err = CreateObjSpecifier(cProperty, &nullDescriptor, formPropertyID,
  189.                                     &keyData, true, selectionSpecifier);
  190.  
  191. AECreateDesc:
  192.     return err;
  193. }
  194.  
  195. //----------------------------------------------------------------------------
  196. // MakeSpecifierForFile
  197. //----------------------------------------------------------------------------
  198. static pascal OSErr MakeSpecifierForFile(FSSpecPtr hfsObj, AEDesc *fileSpecifier)
  199. {
  200.     OSErr        err;
  201.     AEDesc        nullDesc, hfsData;
  202.     AliasHandle    fileAlias;
  203.  
  204.     //
  205.     // Create the file descriptor with the FSSpec passed in.
  206.     //
  207.     err = NewAlias(NULL, hfsObj, &fileAlias);
  208.     require(err == noErr, NewAlias);
  209.  
  210.     HLock((Handle) fileAlias);
  211.     err = AECreateDesc(typeAlias, (Ptr) *fileAlias, 
  212.                 GetHandleSize((Handle) fileAlias), &hfsData);
  213.     HUnlock((Handle) fileAlias);
  214.     DisposeHandle((Handle) fileAlias);
  215.     require(err == noErr, AECreateDesc);
  216.  
  217.     //
  218.     // Make the object specifier with a null container
  219.     // (i.e., "file of <null>", or just "file")
  220.     //
  221.     nullDesc.descriptorType = typeNull;
  222.     nullDesc.dataHandle = NULL;    
  223.     err = CreateObjSpecifier(typeWildCard, &nullDesc, 
  224.                 formAlias, &hfsData, false, fileSpecifier);
  225.  
  226. AECreateDesc:
  227. NewAlias:
  228.     return err;
  229. }
  230.  
  231. //----------------------------------------------------------------------------
  232. // MakePropertySpecifierForSpecifier
  233. //----------------------------------------------------------------------------
  234.  
  235. static pascal OSErr MakePropertySpecifierForSpecifier
  236.     (DescType property, AEDesc *ofSpecifier, AEDesc *propertySpecifier)
  237. {
  238.     OSErr        err;
  239.     AEDesc        keyData;
  240.     
  241.     //
  242.     // Create a 'type' AEDesc with the desired property
  243.     //
  244.     err = AECreateDesc(typeType, (Ptr) &property, sizeof(DescType), &keyData);
  245.     require(err == noErr, AECreateDesc);
  246.  
  247.     //
  248.     // With it create a property specifier for the object specifier
  249.     // passed to us.
  250.     //
  251.     err = CreateObjSpecifier(cProperty, ofSpecifier, 
  252.                 formPropertyID, &keyData, false, propertySpecifier);
  253.  
  254.     (void) AEDisposeDesc(&keyData);    
  255. AECreateDesc:
  256.     return err;
  257. }
  258.  
  259. //----------------------------------------------------------------------------
  260. // GetSizeFromIconType
  261. //----------------------------------------------------------------------------
  262.  
  263. static pascal Size GetSizeFromIconType (DescType iconType)
  264. {
  265.     Size    size = -1;
  266.  
  267.     switch (iconType) {
  268.         case large8BitData:
  269.             size = kLarge8BitIconSize;
  270.             break;
  271.         case large4BitData:
  272.             size = kLarge4BitIconSize;        
  273.             break;
  274.         case large1BitMask:
  275.             size = kLargeIconSize;
  276.             break;
  277.         case small8BitData:
  278.             size = kSmall8BitIconSize;
  279.             break;
  280.         case small4BitData:
  281.             size = kSmall4BitIconSize;
  282.             break;
  283.         case small1BitMask:
  284.             size = kSmallIconSize;
  285.             break;
  286.     }
  287.     return size;
  288. }
  289.  
  290.  
  291. //----------------------------------------------------------------------------
  292. // BuildIconSuiteFromAEDesc
  293. //
  294. // OK, this uses the Apple Event Manager to pick the icon data out of the
  295. // 'ifam' AEDesc.
  296. //----------------------------------------------------------------------------
  297.  
  298. static pascal OSErr BuildIconSuiteFromAEDesc
  299.     (Boolean largeIcons, Handle *iconSuite, AEDesc *iconFam)
  300. {
  301.     OSErr        err;
  302.     Handle         suite, icon;
  303.     AERecord    rec;
  304.     Ptr            buffer;
  305.     DescType    large[3] = {large8BitData, large4BitData, large1BitMask};
  306.     DescType    small[3] = {small8BitData, small4BitData, small1BitMask};
  307.     DescType    *type, iconType, typeCode;
  308.     long        count;
  309.     Size        maxSize, size, iconSize;
  310.     Boolean        maskAdded;
  311.     DescType    maskType;
  312.  
  313.     maskAdded = false;
  314.     suite = NULL;
  315.     maxSize = kLarge8BitIconSize;
  316.  
  317.     if (largeIcons == true) {
  318.         type = large;
  319.         maskType = large1BitMask;
  320.     }
  321.     else {
  322.         type = small;
  323.         maskType = small1BitMask;
  324.     }
  325.  
  326.     buffer = NewPtr(maxSize);
  327.     require(buffer != NULL, NewPtr);
  328.     
  329.     err = NewIconSuite(&suite);
  330.     require(err == noErr, NewIconSuite);
  331.     
  332.     err = AECoerceDesc(iconFam, typeAERecord, (AEDesc *) &rec);
  333.     require(err == noErr, AECoerceDesc);
  334.     
  335.     for (count = 0; count < 3; count ++) {
  336.         //
  337.         // loop through the icons and grab the data from the AERecord for
  338.         // each type of icon we're interested in.
  339.         //
  340.         iconType = type[count];
  341.         size = GetSizeFromIconType(iconType);
  342.         err = AEGetKeyPtr(&rec, iconType, iconType, &typeCode, 
  343.                         buffer, maxSize, &iconSize);
  344.     
  345.         if (err == noErr) {
  346.             //
  347.             // We don't set the error code for this unless the NewHandle
  348.             // call fails, because it's possible that the 'ifam' doesn't
  349.             // have an icon for one that we're interested in.
  350.             //
  351.             icon = NewHandle(size);
  352.     
  353.             if (icon != NULL) {
  354.                 //
  355.                 // OK, the memory alloc succeeded and we have data. Copy
  356.                 // it into the allocated icon and add it to the suite. 
  357.                 // Set atLeastOne to true, to indicate later that we did
  358.                 // in fact add at least one icon to this suite.
  359.                 //
  360.                 BlockMoveData(buffer, *icon, size);
  361.                 err = AddIconToSuite(icon, suite, iconType);
  362.                 if ((err == noErr) && (iconType == maskType))
  363.                     maskAdded = true;
  364.             }
  365.             else
  366.                 err = memFullErr;
  367.         }
  368.     }
  369.  
  370.     (void) AEDisposeDesc(&rec);
  371.  
  372. AECoerceDesc:
  373.     if ((err != noErr) || (maskAdded == false)) {
  374.         //
  375.         // There was either an error in a memory allocation,  or something
  376.         // else went wrong (like no mask was added to the suite).  Get
  377.         // rid of the partially created suite.
  378.         //
  379.         DisposeIconSuite(suite, true);
  380.         suite = NULL;
  381.     }
  382.  
  383. NewIconSuite:
  384.     DisposePtr(buffer);
  385.  
  386. NewPtr:
  387.     *iconSuite = suite;
  388.     return err;
  389. }
  390.  
  391. //----------------------------------------------------------------------------
  392. // GetIconSuiteFromFinder
  393. //
  394. // Send a GetData AE for the 'ifam'
  395. //----------------------------------------------------------------------------
  396. OSErr GetIconSuiteFromFinder (FSSpecPtr hfsObj, Handle *iconSuite)
  397. {
  398.     OSErr        err;
  399.     AppleEvent    finderEvent, replyEvent;
  400.     AEDesc        fileSpecifier, iconPropertySpecifier;
  401.     DescType    returnType;
  402.     Size        returnSize;
  403.     long        returnLong;
  404.     AEDesc        iconFamily;
  405.  
  406.     //
  407.     // Set up our locals for easy cleanup
  408.     //
  409.     *iconSuite = NULL;
  410.  
  411.     //
  412.     // Make sure the Finder is scriptable and is running.
  413.     //
  414.     err = paramErr;
  415.     require(HaveScriptableFinder() == true, HaveScriptableFinder);
  416.  
  417.     //
  418.     // Make a GetData Apple event to send to the Finder
  419.     //
  420.     err = MakeAppleEvent(kAECoreSuite, kAEGetData, &pFinderTarget, 
  421.                 &finderEvent);
  422.     require(err == noErr, MakeAppleEvent);
  423.     
  424.     //
  425.     // Make an object specifier for the interesting file
  426.     //
  427.     err = MakeSpecifierForFile(hfsObj, &fileSpecifier);
  428.     require(err == noErr, MakeSpecifierForFile);
  429.     
  430.     //
  431.     // Make an icon family property specifier for the file
  432.     //
  433.     err = MakePropertySpecifierForSpecifier(pIconBitmap, &fileSpecifier, 
  434.                 &iconPropertySpecifier);
  435.     require(err == noErr, MakePropertySpecifierForSpecifier);
  436.     
  437.     //
  438.     // Stuff it in the Apple event and send it
  439.     //
  440.     err = AEPutParamDesc(&finderEvent, keyDirectObject, &iconPropertySpecifier);
  441.     require(err == noErr, AEPutParamDesc);
  442.  
  443.     err = SendAppleEvent(&finderEvent, &replyEvent,
  444.                 kAEWaitReply + kAECanInteract + kAECanSwitchLayer);
  445.     require(err == noErr, SendAppleEvent);
  446.     
  447.     //
  448.     // Now the Finder may have sent us an error number
  449.     //
  450.     err = AEGetParamPtr(&replyEvent, keyErrorNumber, typeLongInteger, 
  451.                         &returnType, &returnLong, sizeof(long), &returnSize);
  452.  
  453.     if (err == noErr)
  454.         err = (OSErr) returnLong;
  455.     else if (err == errAEDescNotFound)
  456.         err = noErr;
  457.  
  458.     //
  459.     // If not, get the icon family and build an icon suite
  460.     //
  461.  
  462.     if (!err)
  463.     {        
  464.         err = AEGetParamDesc(&replyEvent, keyDirectObject, typeWildCard, &iconFamily);    
  465.         require(err == noErr, AEGetParamDesc);
  466.         err = BuildIconSuiteFromAEDesc(true, iconSuite, &iconFamily);
  467.     }
  468.  
  469.     //
  470.     // Clean up and exit
  471.     //
  472.  
  473.     (void) AEDisposeDesc(&iconFamily);
  474.  
  475. AEGetParamDesc:
  476.     (void) AEDisposeDesc(&replyEvent);
  477.  
  478. SendAppleEvent:
  479. AEPutParamDesc:
  480.     (void) AEDisposeDesc(&iconPropertySpecifier);
  481.  
  482. MakePropertySpecifierForSpecifier:
  483.     (void) AEDisposeDesc(&fileSpecifier);
  484.  
  485. MakeSpecifierForFile:
  486.     (void) AEDisposeDesc(&finderEvent);
  487.  
  488. MakeAppleEvent:
  489. HaveScriptableFinder:
  490.     return err;
  491. }
  492.